# -*- coding: utf-8 -*-
""" Abstract Line Editor module for float handling

    :Author:
      - 20120111 Roberto Vidmar

    :Revision:  $Revision: 52 $
                $Date: 2012-11-12 09:07:15 +0000 (Mon, 12 Nov 2012) $

    :Copyright: 2011-2012
                Nicola Creati <ncreati@inogs.it>
                Roberto Vidmar <rvidmar@inogs.it>

    :License: MIT/X11 License (see :download:`license.txt
                               <../../license.txt>`)
"""

from qtCompat import QtCore, QtGui

#===============================================================================
class FValidator(QtGui.QRegExpValidator):
  """ A validator for Floats in formats defined by Regular Expression
  """
  def __init__(self, parent, regexp):
    """ Create a new instance of the validator.

     .. note:: parent `AND` regexp must be supplied.

    :param parent: parent widget
    :type parent: QtGui widget
    :param regexp: regular expression that will be used for validation.
    :type regexp: QtCore.QRegExp
    :raises:
    """
    qregexp = QtCore.QRegExp(regexp)
    super(FValidator, self).__init__(qregexp, parent)

#===============================================================================
class AbstractFEditor(QtGui.QLineEdit):
  """ Abstract Line Editor class for floats handling
  """
  def __init__(self, parent):
    """ Create a new instance of the editor.

     .. note:: This class should not be used without subclassing.

    :param parent: parent widget
    :type parent: QtGui widget
    :raises:
    """

    super(AbstractFEditor, self).__init__(self.defaultValue, parent)

    self.pWidget = self.parent()

    font = QtGui.QFont("Courier New", 12, QtGui.QFont.Bold)
    font.setLetterSpacing(QtGui.QFont.AbsoluteSpacing, -0.5)
    self.setFont(font)

    # Set Validator
    validator = FValidator(self, self.regexp)
    self.setValidator(validator)
    # Set Input Mask (needed to activate overwrite mode)
    inputMask = ("x") * len(self.defaultValue)
    self.setInputMask(inputMask)

    # Set line editor width in number of characters
    fm = QtGui.QFontMetrics(self.font())
    width = fm.width(self.inputMask())
    self.setMinimumWidth(width)
    self.setMaximumWidth(width)
    self.setAlignment(self.pWidget.align)

  def signAndText(self):
    """ Return sign and text of this QLineEdit

    :returns: sign and text of this QLineEdit
    :rtype: tuple
    :raises:
    """
    t = self.text()
    if t[0] == '+':
      return '+', t
    else:
      return '-', t

  def fvalue(self):
    """ Return widget floating point value

    :returns: floating point value
    :rtype: float
    :raises:
    """
    return float(self.value())

  def svalue(self):
    """ Return widget text

    :returns: text content
    :rtype: string
    :raises:
    """
    return self.text()

  def setValue(self, value):
    """ Set Editor value

    :param value: value to set
    :type value: string, int or float
    :raises:
    """
    self.setText(self.asString(value))

#===============================================================================
class FEditor(AbstractFEditor):
  """ Signed Float Line Editor

      Will contain float numbers with the format **[+-]hhhh.hhh**
  """
  def __init__(self, parent, hchr):
    """ Create a new instance of the editor.

    :param parent: parent widget
    :type parent: QtGui widget
    :param hcr: a character for the `units`
    :type hcr:  string
    :raises:
    """
    self.hchr = hchr
    self.regexp = (u"[+-][0-9]{4}\.\d{%s}%s%s" % (parent.decimals,
      u"\N{NO-BREAK SPACE}", hchr))

    self.fmt = "%%s%%0%d.%df%s%s" % (parent.heightLen + 1 + parent.decimals,
      parent.decimals, u"\N{NO-BREAK SPACE}", hchr)

    self.defaultValue = self.fmt % ('+', 0.)
    super(FEditor, self).__init__(parent)

  def value(self):
    """ Return signed widget string value

    :returns: signed widget string value
    :rtype: string
    :raises:
    """
    sign, t = super(FEditor, self).signAndText()
    dd = str(t[1: -(len(self.hchr) + 1)])
    return sign + dd

  def asString(self, value):
    """ Return value as formatted string

        Format is embedded into class.

    :param value: numerical value
    :type value: float or int
    :returns: `value` as formatted string
    :rtype: string
    :raises:
    """
    if value < 0:
      signchr = '-'
    else:
      signchr = '+'
    return self.fmt % (signchr, abs(value))

#===============================================================================
class UFEditor(AbstractFEditor):
  """ Unsigned Float Line Editor

      Will contain unsigned floats with the format **hhhh.hhh**
  """
  def __init__(self, parent):
    self.regexp = (u"[0-9]{%s}\.\d{%s}" % (parent.coordLen, parent.decimals))

    self.fmt = "%%0%d.%df" % (parent.coordLen + 1 + parent.decimals,
      parent.decimals)

    #print "fmt=", self.fmt, self.regexp
    self.defaultValue = self.fmt % 0.
    super(UFEditor, self).__init__(parent)

  def value(self):
    """ Return widget string value

    :returns: widget string value
    :rtype: string
    :raises:
    """
    return self.text()

  def asString(self, value):
    """ Return value as formatted string

        Format is embedded into class.

    :param value: numerical value
    :type value: float or int
    :returns: `value` as formatted string
    :rtype: string
    :raises:
    """
    return self.fmt % value
